package com.sunwayworld.basemodule.rm.equipment.equiptreturn.service.impl;

import com.sunwayworld.basemodule.rm.equipment.bean.LimsEquipmentBean;
import com.sunwayworld.basemodule.rm.equipment.equiptborrow.bean.LimsEquiptBorrowBean;
import com.sunwayworld.basemodule.rm.equipment.equiptborrow.service.LimsEquiptBorrowService;
import com.sunwayworld.basemodule.rm.equipment.equiptreturn.bean.LimsEquiptReturnBean;
import com.sunwayworld.basemodule.rm.equipment.equiptreturn.dao.LimsEquiptReturnDao;
import com.sunwayworld.basemodule.rm.equipment.equiptreturn.service.LimsEquiptReturnService;
import com.sunwayworld.basemodule.rm.equipment.service.LimsEquipmentService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.audit.aunnotation.Audit;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.support.auditable.bean.CoreBpmnParameterDTO;
import com.sunwayworld.framework.utils.CollectionUtils;
import com.sunwayworld.framework.utils.ObjectUtils;
import com.sunwayworld.module.sys.bpmn.bean.CoreBpmnInstanceStatusDTO;
import com.sunwayworld.module.sys.bpmn.diagram.ProcessStatus;
import com.sunwayworld.module.sys.bpmn.engine.CoreBpmnRuntimeService;
import com.sunwayworld.module.sys.bpmn.engine.CoreBpmnRuntimeSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsEquiptReturnServiceImpl implements LimsEquiptReturnService {

    @Autowired
    private LimsEquiptReturnDao limsEquiptReturnDao;
    @Autowired
    private LimsEquipmentService limsEquiptService;

    @Autowired
    private LimsEquiptBorrowService equiptBorrowService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsEquiptReturnDao getDao() {
        return limsEquiptReturnDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsEquiptReturnBean limsEquiptReturn = jsonWrapper.parseUnique(LimsEquiptReturnBean.class);
        limsEquiptReturn.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsEquiptReturn);
        // 将归还ID写入到借用记录上
        if (!ObjectUtils.isEmpty(limsEquiptReturn.getEquiptBorrowId())) {
            LimsEquiptBorrowBean equiptBorrow = equiptBorrowService.selectById(limsEquiptReturn.getEquiptBorrowId());
            if (!ObjectUtils.isEmpty(equiptBorrow)) {
                equiptBorrow.setEquiptReturnId(limsEquiptReturn.getId());
                equiptBorrowService.getDao().update(equiptBorrow, "EQUIPTRETURNID");
            }
        }
        return limsEquiptReturn.getId();
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.DELETE)
    public void delete(RestJsonWrapperBean jsonWrapper) {
        List<LimsEquiptReturnBean> limsEquiptReturns = jsonWrapper.parse(LimsEquiptReturnBean.class);
        if (CollectionUtils.isEmpty(limsEquiptReturns)) {
            return;
        }
        // 查询原借用数据
        limsEquiptReturns = selectListByIds(limsEquiptReturns.stream()
            .map(LimsEquiptReturnBean::getId).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(limsEquiptReturns)) {
            return;
        }
        // 清除相关借用记录的归还ID
        List<Long> equiptBorrowIds = limsEquiptReturns.stream().filter(u->!ObjectUtils.isEmpty(u.getEquiptBorrowId()))
            .map(LimsEquiptReturnBean::getEquiptBorrowId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(equiptBorrowIds)) {
            List<LimsEquiptBorrowBean> equiptBorrows =
                    equiptBorrowService.selectListByIds(equiptBorrowIds);
            if (!ObjectUtils.isEmpty(equiptBorrows)) {
                equiptBorrows.forEach(u->u.setEquiptReturnId(null));
                equiptBorrowService.getDao().update(equiptBorrows, "EQUIPTRETURNID");
            }
        }
        getDao().deleteBy(limsEquiptReturns);
    }

    @Transactional
    @AuditTrailEntry(AuditTrailType.PROCESS_COMPLETE)
    @Audit("AUDIT.PROCESS_COMPLETE")
    @Override
    public List<CoreBpmnInstanceStatusDTO<Long>> completeTask(RestJsonWrapperBean wrapper) {
        List<LimsEquiptReturnBean> itemList = wrapper.parse(this.getDao().getType());
        if (itemList.isEmpty()) {
            return CollectionUtils.emptyList();
        } else {
            this.checkAndUpdateVersion(itemList);
            CoreBpmnRuntimeService runtimeService = (CoreBpmnRuntimeService)ApplicationContextHelper.getBean(CoreBpmnRuntimeService.class);
            List<Long> itemIdList = (List)itemList.stream().map((i) -> {
                return (Serializable)i.getId();
            }).collect(Collectors.toList());
            List<LimsEquiptReturnBean> selectItemList = this.getBpmnVarsItemList(itemIdList);
            List<CoreBpmnRuntimeSource<LimsEquiptReturnBean, Long>> runtimeSourceList = this.parseAuditableRuntimeSource(itemIdList, CoreBpmnParameterDTO.of(wrapper), this.getBpmnVars(wrapper, selectItemList));
            List<CoreBpmnInstanceStatusDTO<Long>> coreBpmnInstanceStatusDTOS = runtimeService.completeTask(runtimeSourceList);
            List<CoreBpmnInstanceStatusDTO<Long>> flagList = coreBpmnInstanceStatusDTOS.stream().filter(e -> ObjectUtils.equals(e.getProcessStatus(), ProcessStatus.DONE)).collect(Collectors.toList());
            if (!flagList.isEmpty()) {
                // 流程走完更新设备状态 借用->在用
                List<Long> idList = selectItemList.stream().map(equipt -> equipt.getEquiptId()).collect(Collectors.toList());
                List<LimsEquipmentBean> LimsEquipmentBeans = limsEquiptService.selectListByIds(idList);
                // 流程结束更新设备状态
                if (!LimsEquipmentBeans.isEmpty()) {
                    LimsEquipmentBeans.stream().forEach(equipt->equipt.setEquipState("normal"));
                    limsEquiptService.getDao().update(LimsEquipmentBeans,"equipState");
                }
                // 更新设备归还时间
                selectItemList.stream().forEach(equipt->equipt.setReturnTime(LocalDateTime.now()));
                this.getDao().update(selectItemList,"RETURNTIME");
            }
            return coreBpmnInstanceStatusDTOS;
        }
    }
}
